package obecto.core
{
	import flash.events.IEventDispatcher;
	import flash.system.ApplicationDomain;
	
	import obecto.metadata.EventHandlerDirective;
	import obecto.metadata.MetadataDirectives;
	import obecto.metadata.ViewContractDirective;
	import obecto.utility.MetaUtility;
	
	public class FLController implements IFLController
	{
		protected namespace handler = "flit.metadata.event.handler";
		
		private var _component : FLUIComponent;
		[Bindable]
		public function set component(value : FLUIComponent) : void
		{
			if (value != null && value != _component)
			{
				if (_component != null)
				{
					detachEventHandlers();
				}
				
				_component = value;
				applyContractDirectives();
				attachEventHandlers();
			}
		}
		public function get component() : FLUIComponent
		{
			return _component;
		}
		
		private var metadata : MetadataDirectives;
		
		public function FLController()
		{
			metadata = MetaUtility.resolveMetadata(this);
		}
		
		private function applyContractDirectives() : void 
		{
			for each (var contract : ViewContractDirective in metadata.viewContracts) 
			{
				if ((component as Object).hasOwnProperty(contract.property)) 
				{
					var requiredType : Class = ApplicationDomain.currentDomain.getDefinition(contract.type) as Class;
					
					if (component[contract.property] is requiredType) 
					{
						this[contract.property] = component[contract.property];
					}
				}
			}
		}
		
		private function detachEventHandlers() : void 
		{
			for each (var directive : EventHandlerDirective in metadata.eventHandlers) 
			{
				var h : Function = this.handler::[directive.handler] as Function;
				var d : IEventDispatcher = this[directive.dispatcher] as IEventDispatcher;
				
				if (d != null) 
				{
					d.removeEventListener(directive.event, h, false);
				}
			}
		}
		
		private function attachEventHandlers() : void 
		{
			for each (var directive : EventHandlerDirective in metadata.eventHandlers) 
			{
				var h : Function = this.handler::[directive.handler] as Function;
				var d : IEventDispatcher = this[directive.dispatcher] as IEventDispatcher;
				
				if (d != null) 
				{
					d.addEventListener(directive.event, h, false, 0, true);
				}
			}
		}
	}
}